/** bcmi_frame main scheduler
 *
 *  bcmi_frame main scheduler
 *
 *  @author : huicong
 *  @date : 2008-10-30
 *
 */

#include "ParallelFrame.h"

#include <sstream>
#include <iostream>
#include <fstream>
using namespace std;

namespace bcmi_frame
{

    ParallelFrame::ParallelFrame(INOUT INT argc, INOUT CHAR **argv):
                   _executeFlag(FALSE)
    {
        MPI_Init(&argc, &argv);
        MPI_Comm_rank(MPI_COMM_WORLD, &_mpiMyProcessId);
        MPI_Comm_size(MPI_COMM_WORLD, &_mpiProcessNumber);

        _frameClock = new FrameClock();

        stringstream _logNameBuffer;
        _logNameBuffer << LOGFILE_PRE << _mpiMyProcessId;
        _frameLogRecorder = new LogRecorder((CSTRING)_logNameBuffer.str().c_str(), _frameClock);

        _mpiTransferBufferPoolNumber = bcmi_frame::DEFAULT_MAX_POOL_NUMBER;
        _mpiTransferBufferPoolSize = bcmi_frame::DEFAULT_MAX_POOL_SIZE;

        _frameJobSystem = new JobSystem(this);

#ifdef LOG_PARALLEL_FRAME
        {
            stringstream _logInfoBuffer;
            _logInfoBuffer << "BCMI_Frame parallel frame system has been started, mpi process id = " 
                << _mpiMyProcessId << " , all process number = " << _mpiProcessNumber;
            _frameLogRecorder->log(
                H_OK,
                bcmi_frame::FRAME,
                __FUNCSIG__,
                (CSTRING)_logInfoBuffer.str().c_str()
                );
        }
#endif //#ifdef LOG_PARALLEL_FRAME

#ifdef DEBUG_PARALLEL_FRAME
        cout << "BCMI_Frame parallel frame system has been started, mpi process id = " 
            << _mpiMyProcessId << " , all process number = " << _mpiProcessNumber << endl;
#endif //#ifdef DEBUG_PARALLEL_FRAME
    }

    ParallelFrame::~ParallelFrame()
    {
#ifdef LOG_PARALLEL_FRAME
        _frameLogRecorder->log(
            H_OK,
            bcmi_frame::FRAME,
            __FUNCSIG__,
            "BCMI_Frame parallel frame system has been stop."
            );
#endif //#ifdef LOG_PARALLEL_FRAME
        delete _frameLogRecorder;
        _frameLogRecorder = NULL;
        delete _frameClock;
        _frameClock = NULL;
        delete _frameJobSystem;
        _frameJobSystem = NULL;

        MPI_Finalize();
    }

    LogRecorder* ParallelFrame::getLogRecorder()
    {
        return _frameLogRecorder;
    }

    INT ParallelFrame::getMPIProcessId()
    {
        return _mpiMyProcessId;
    }

    INT ParallelFrame::getMPIProcessNumber()
    {
        return _mpiProcessNumber;
    }

    DOUBLE ParallelFrame::getMPITime()
    {
        return _frameClock->getCurrentMPITime();
    }

    INT64 ParallelFrame::getSystemTime()
    {
        return _frameClock->getCurrentSystemTime();
    }

    VOID ParallelFrame::setMPITransferBufferPoolNumber(IN UINT _number)
    {
        if (TRUE == _executeFlag) // running , do nothing
        {
            return;
        }
#ifdef LOG_PARALLEL_FRAME
        {
            stringstream _infoBuffer;
            _infoBuffer << "set mpi transfer buffer pool number : " << _number;
            _frameLogRecorder->log(
                H_OK,
                bcmi_frame::FRAME,
                __FUNCSIG__,
                (CSTRING)_infoBuffer.str().c_str()
                );
        }
#endif //#ifdef LOG_PARALLEL_FRAME
        _mpiTransferBufferPoolNumber = _number;
    }

    UINT ParallelFrame::getMPITransferBufferPoolNumber()
    {
        return _mpiTransferBufferPoolNumber;
    }

    UINT ParallelFrame::getMPITransferBufferPoolSize()
    {
        return _mpiTransferBufferPoolSize;
    }

    VOID ParallelFrame::setMPITransferBufferPoolSize(IN UINT _size)
    {
        if (TRUE == _executeFlag) // running , do nothing
        {
            return;
        }
#ifdef LOG_PARALLEL_FRAME
        {
            stringstream _infoBuffer;
            _infoBuffer << "set mpi transfer buffer pool size : " << _size;
            _frameLogRecorder->log(
                H_OK,
                bcmi_frame::FRAME,
                __FUNCSIG__,
                (CSTRING)_infoBuffer.str().c_str()
                );
        }
#endif //#ifdef LOG_PARALLEL_FRAME
        _mpiTransferBufferPoolSize = _size;
    }

    JobSystem* ParallelFrame::getJobSystem()
    {
        return _frameJobSystem;
    }

    HRESULT ParallelFrame::execute()
    {
        HRESULT hr = H_OK;
        //UNDO
        _frameJobSystem->execute();
        return hr;
    }

}; //namespace bcmi_frame